#ifndef __UTIL_HPP__
#define __UTIL_HPP__
#include "logger.hpp"
#include <iostream>
#include <sstream>
#include <fstream>
#include <memory>
#include <vector>
#include <string>
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>

class mysql_util{
    public:
        static MYSQL*mysql_create(const std::string &host,
            const std::string& username,
            const std::string& password,
            const std::string& dbname,
            uint16_t port=3306){
                 //1. 初始化mysql句柄
                MYSQL* mysql= mysql_init(nullptr);
                if(mysql==nullptr){
                    ELOG("mysql init failed\n");
                    return nullptr;
                }
                //2. 连接服务器
                if(mysql_real_connect(mysql,host.c_str(),username.c_str(),password.c_str(),dbname.c_str(),port,NULL,0)==NULL){
                    ELOG("connect mysql server fialed: %d\n",mysql_error(mysql));
                    mysql_close(mysql);
                    return nullptr;
                }
                //3. 设置客户端字符集
                int ret=mysql_set_character_set(mysql,"utf8");
                if(ret!=0){
                    ELOG("set cilent character fialed: %s \n",mysql_error(mysql));
                    mysql_close(mysql);
                    return nullptr;
                }
                return mysql;
            }

        static bool mysql_exec(MYSQL*mysql,const std::string& sql){
            int ret=mysql_query(mysql,sql.c_str());
            if(ret!=0){
            ELOG("%s\n",sql);
            ELOG("mysql query failed : %s \n",mysql_error(mysql));
            mysql_close(mysql);
            return false;
            } 
            return true;  
        }

        static void mysql_destroy(MYSQL*mysql){
            if(mysql!=nullptr){
                mysql_destroy(mysql);
            }  
        }
};


class json_util{
    public:
        static bool serialize(const Json::Value &root,std::string &str){
            //实例化一个StreamWriterBuilder 工厂类对象
            Json::StreamWriterBuilder swb;
            //通过StreamWriterBuilder工厂类对象生产一个StreamWrite对象
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            //使用StreamWrite对象，对Json::Value中存储的数据进行反序列化
            std::stringstream ss;
            int ret =sw->write(root, &ss);
            if(ret!=0){
                ELOG("Serialize failed!\n");
                return false;
            }
            str=ss.str();
            return true;

        }

        static bool unserialize(const std::string&str,Json::Value &root){
            //1. 实列化一个CharReaderBuilder工厂类对象
            Json::CharReaderBuilder crb;
            //2. 使用CharReaderBuilder 工厂类生产一个CharRead
            // Json::CharReader* cr=crb.newCharReader();
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            //3. 定义一个Json::Value对象存储解析后的数据
            std::string err;
            //4. 使用CharRead对象进行Json格式化字符串str的反序化
            bool ret=cr->parse(str.c_str(),str.c_str()+str.size(),&root,&err);
            if(ret==false){
                ELOG("json unserialize failed: %s",err.c_str());
                return false;
            }
            return true;
        }
};


class string_util{
    public:
        static int split(const std::string& src,const std::string seq,std::vector<std::string>& res){
            size_t idx=0,pos=0;
            while(idx<src.size()){
                pos=src.find(seq,idx);
                if(pos==std::string::npos){
                    //没有找到，字符串中没有间隔符了
                    res.push_back(src.substr(idx));
                    break;
                }
                if(idx==pos){
                    idx=pos+seq.size();
                    continue;
                }
                res.push_back(src.substr(idx,pos-idx));
                idx=pos+seq.size();
            }
            return res.size();  
        }
};



class file_util{
    public:
        static bool read(const std::string& filename,std::string& body){
            //1.打开文件
            std::ifstream ifs(filename,std::ios::binary);
            if(ifs.is_open()==false){
                ELOG("%s file open failed!!",filename.c_str());
                return false;
            }
            //2.获取文件大小
            size_t fsize=0;
            ifs.seekg(0,std::ios::end);
            fsize=ifs.tellg();
            ifs.seekg(0,std::ios::beg);
            body.resize(fsize);
            //3.将所有数据读取出来
            ifs.read(&body[0],fsize);//注意这里不能用body.c_str(),因为这个的返回值是const
            if(ifs.good()==false){
                ELOG("read %s file content failed!",filename.c_str());
                ifs.close();
                return false;
            }
            //4.关闭文件
            ifs.close();
            return true;
        }

};

#endif